#include "g_local.h"
#include "../cola/cola_napi.h"

#define MAX_ENTITY_NAMES		100000
#define MAX_CLASS_NAMES			200000
#define MAX_CLASS_ASSOCIATIONS	512


static char entNameString[MAX_ENTITY_NAMES];
static int entNameOffset;

static char classNameString[MAX_CLASS_NAMES];
static int classNameOffset;

// These are separate so the second can be quickly passed to LoadTypes
static char *entNames[MAX_CLASS_ASSOCIATIONS];
static char *classNames[MAX_CLASS_ASSOCIATIONS];
static int numClassAssociations;

static int commandMode;

void G_ColaInitServer( void )
{
	numClassAssociations = 0;
	commandMode = 0;
}

void G_ColaEnableCommandMode( void )
{
	commandMode = 1;
}

void G_ColaDisableCommandMode( void )
{
	commandMode = 0;
}

void G_EchoAssociations( void )
{
	int i;

	for(i=0;i<numClassAssociations;i++)
	{
		G_Printf("%i: %s --> %s\n", i, entNames[i], classNames[i]);
	}
}

COLA_INLINE colaExecStatus_t colaServerPrintString(colaThread_t *thread, colaString_t *str)
{
	G_Printf("%s", str->str);
	return COLA_EXEC_OK;
}

COLA_INLINE colaExecStatus_t colaServerRegisterSpawnableStringString(colaThread_t *thread, colaString_t *mapName, colaString_t *typeName)
{
	// See if there's enough room
	if(entNameOffset + mapName->length + 1 >= MAX_ENTITY_NAMES)
		G_Error("Entity name pool overflow");
	if(classNameOffset + typeName->length + 1 >= MAX_CLASS_NAMES)
		G_Error("Entity association pool overflow");
	if(numClassAssociations + 1 == MAX_CLASS_ASSOCIATIONS)
		G_Error("Entity/class binding overflow");

	// Copy map name
	strcpy(entNameString + entNameOffset, mapName->str);
	entNames[numClassAssociations] = entNameString + entNameOffset;
	entNameOffset += mapName->length + 1;

	// Copy class name
	strcpy(classNameString + classNameOffset, typeName->str);
	classNames[numClassAssociations] = classNameString + classNameOffset;
	classNameOffset += typeName->length + 1;

	numClassAssociations++;

	return COLA_EXEC_OK;
}

COLA_INLINE colaExecStatus_t colaServerRegisterClientClassString(colaThread_t *thread, colaString_t *className)
{
	return COLA_EXEC_OK;
}

COLA_INLINE colaExecStatus_t colaServerCmdArgvInteger(colaThread_t *thread, colaString_t *rv, colaInteger_t *index)
{
	char cmd[1024];

	if(!commandMode)
	{
		// Return a blank string
		COLA_ASSERT_CALL(colaMakeString(thread, rv, 0));
		return COLA_EXEC_OK;
	}

	// Get the argument
	trap_Argv( *index, cmd, sizeof( cmd ) );
	cmd[1023] = '\0';

	COLA_ASSERT_CALL(colaNTCAToString(thread, rv, cmd));
	return COLA_EXEC_OK;
}

char	*ConcatArgs( int start );

COLA_INLINE colaExecStatus_t colaServerCmdArgvSequencedInteger(colaThread_t *thread, colaString_t *rv, colaInteger_t *index)
{
	if(!commandMode)
	{
		// Return a blank string
		COLA_ASSERT_CALL(colaMakeString(thread, rv, 0));
		return COLA_EXEC_OK;
	}

	COLA_ASSERT_CALL(colaNTCAToString(thread, rv, ConcatArgs(*index)));
	return COLA_EXEC_OK;
}

COLA_INLINE colaExecStatus_t colaServerCmdArgc(colaThread_t *thread, colaInteger_t *rv)
{
	if(!commandMode)
	{
		*rv = 0;
		return COLA_EXEC_OK;
	}
	*rv = trap_Argc();
	return COLA_EXEC_OK;
}

#include "g_cola_server.h"

colaAPI_t *G_ColaServerAPI( void )
{
	return &colaStubAPI;
}
